﻿using CNative.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;

namespace CNative.Dapper.Utils
{
    #region class DbFirstProvider
    public partial class DbFirstProvider : IDbFirst
    {
        #region Properties
        public virtual DbHelper Context { get; set; }
        protected bool IsBackupTable { get; set; }
        protected int MaxBackupDataRows { get; set; }
        protected virtual int DefultLength { get; set; }
        public DbFirstProvider()
        {
            if (DefultLength == 0)
            {
                DefultLength = 255;
            }
        }
        public DbFirstProvider(DbHelper _Context) : this()
        {
            Context = _Context;
        }
        public DbFirstProvider(string dbName) : this()
        {
            Context = new DbHelper(dbName);
        }
        #endregion

        #region Public methods
        public virtual IDbFirst BackupTable(int maxBackupDataRows = int.MaxValue)
        {
            this.IsBackupTable = true;
            this.MaxBackupDataRows = maxBackupDataRows;
            return this;
        }
        public virtual IDbFirst SetStringDefaultLength(int length)
        {
            DefultLength = length;
            return this;
        }
        public virtual void InitTables(Type entityType)
        {
            Funs.CacheRemoveAll();
            if (!this.Context.SqlDbProvider.IsAnySystemTablePermissions())
            {
                Check.Exception(true, "Dbfirst and  Codefirst requires system table permissions");
            }
            Execute(entityType);
            //Check.Exception(!executeResult.IsSuccess, executeResult.ErrorMessage);
        }
        public void InitTables<T>()
        {
            InitTables(typeof(T));
        }
        public void InitTables<T, T2>()
        {
            InitTables(typeof(T), typeof(T2));
        }
        public void InitTables<T, T2, T3>()
        {
            InitTables(typeof(T), typeof(T2), typeof(T3));
        }
        public void InitTables<T, T2, T3, T4>()
        {
            InitTables(typeof(T), typeof(T2), typeof(T3), typeof(T4));
        }
        public virtual void InitTables(params Type[] entityTypes)
        {
            if (entityTypes.HasValue())
            {
                foreach (var item in entityTypes)
                {
                    try
                    {
                        InitTables(item);
                    }
                    catch (Exception ex)
                    {

                        throw new Exception(item.Name + " 创建失败,请认真检查 1、属性需要get set 2、特殊类型需要加Ignore 具体错误内容： " + ex.Message);
                    }
                }
            }
        }
        public virtual void InitTables(string entitiesNamespace)
        {
            var types = Assembly.Load(entitiesNamespace).GetTypes();
            InitTables(types);
        }
        public virtual void InitTables(params string[] entitiesNamespaces)
        {
            if (entitiesNamespaces.HasValue())
            {
                foreach (var item in entitiesNamespaces)
                {
                    InitTables(item);
                }
            }
        }
        #endregion

        #region Core Logic
        protected virtual void Execute(Type entityType)
        {
            var entityInfo = Funs.GetDbTableInfo(this.Context, entityType);
            if (this.DefultLength > 0)
            {
                foreach (var item in entityInfo.Columns)
                {
                    if (item.PropertyInfo.PropertyType == Constants.StringType && item.Type.IsNullOrEmpty() && item.MaxLength == 0)
                    {
                        item.MaxLength = DefultLength;
                    }
                }
            }
            var isAny = this.Context.SqlDbProvider.IsAnyTable(entityInfo.TableName);
            if (isAny && entityInfo.IsDisabledUpdateAll)
            {
                return;
            }
            if (isAny)
                ExistLogic(entityInfo);
            else
                NoExistLogic(entityInfo);

            this.Context.SqlDbProvider.AddRemark(entityInfo);
            this.Context.SqlDbProvider.AddIndex(entityInfo);
            this.Context.SqlDbProvider.AddDefaultValue(entityInfo);
        }
        public virtual void NoExistLogic(DbTableInfo entityInfo)
        {
            var tableName = entityInfo.TableName;
            //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimaryKey).Count() > 1, "Use Code First ,The primary key must not exceed 1");
            List<DbColumnInfo> columns = new List<DbColumnInfo>();
            if (entityInfo.Columns.HasValue())
            {
                foreach (var item in entityInfo.Columns.OrderBy(it => it.IsPrimaryKey ? 0 : 1).Where(it => it.IsIgnore == false))
                {
                    DbColumnInfo dbColumnInfo = EntityColumnToDbColumn(entityInfo, tableName, item);
                    columns.Add(dbColumnInfo);
                }
            }
            this.Context.SqlDbProvider.CreateTable(tableName, columns, true);
        }
        public virtual void ExistLogic(DbTableInfo entityInfo)
        {
            if (entityInfo.Columns.HasValue() && entityInfo.IsDisabledUpdateAll == false)
            {
                //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimaryKey).Count() > 1, "Multiple primary keys do not support modifications");

                var tableName = GetTableName(entityInfo);
                var dbColumns = this.Context.SqlDbProvider.GetColumnInfosByTableName(tableName);
                ConvertColumns(dbColumns);
                var entityColumns = entityInfo.Columns.Where(it => it.IsIgnore == false).ToList();
                var dropColumns = dbColumns
                                          .Where(dc => !entityColumns.Any(ec => dc.Name.Equals(ec.Name, StringComparison.CurrentCultureIgnoreCase)))
                                          .ToList();
                var addColumns = entityColumns
                                           .Where(ec => ec.Name.IsNullOrEmpty() || !dbColumns.Any(dc => dc.Name.Equals(ec.Name, StringComparison.CurrentCultureIgnoreCase)))
                                           .Where(ec => !dbColumns.Any(dc => ec.Name.Equals(dc.Name, StringComparison.CurrentCultureIgnoreCase))).ToList();
                var alterColumns = entityColumns
                                           .Where(ec => !dbColumns.Any(dc => dc.Name.Equals(ec.Name, StringComparison.CurrentCultureIgnoreCase)))
                                           .Where(ec =>
                                                          dbColumns.Any(dc => dc.Name.Equals(ec.Name)
                                                               && ((ec.MaxLength != dc.MaxLength && !Funs.GetUnderType(ec.PropertyInfo).IsEnum() && Funs.GetUnderType(ec.PropertyInfo).IsIn(Constants.StringType)) ||
                                                                    ec.IsNullable != dc.IsNullable
                                                                    ))).ToList();
                var renameColumns = entityColumns
                    .Where(it => !string.IsNullOrEmpty(it.Name))
                    .Where(entityColumn => dbColumns.Any(dbColumn => entityColumn.Name.Equals(dbColumn.Name, StringComparison.CurrentCultureIgnoreCase)))
                    .ToList();


                var isMultiplePrimaryKey = dbColumns.Where(it => it.IsPrimaryKey).Count() > 1 || entityColumns.Where(it => it.IsPrimaryKey).Count() > 1;


                var isChange = false;
                foreach (var item in addColumns)
                {
                    this.Context.SqlDbProvider.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item));
                    isChange = true;
                }
                if (entityInfo.IsDisabledDelete == false)
                {
                    foreach (var item in dropColumns)
                    {
                        this.Context.SqlDbProvider.DropColumn(tableName, item.Name);
                        isChange = true;
                    }
                }
                foreach (var item in alterColumns)
                {
                    this.Context.SqlDbProvider.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item));
                    isChange = true;
                }
                foreach (var item in renameColumns)
                {
                    this.Context.SqlDbProvider.RenameColumn(tableName, item.Name, item.Name);
                    isChange = true;
                }

                foreach (var item in entityColumns)
                {
                    var dbColumn = dbColumns.FirstOrDefault(dc => dc.Name.Equals(item.Name, StringComparison.CurrentCultureIgnoreCase));
                    if (dbColumn == null) continue;
                    bool pkDiff, idEntityDiff;
                    KeyAction(item, dbColumn, out pkDiff, out idEntityDiff);
                    if (dbColumn != null && pkDiff && !idEntityDiff && isMultiplePrimaryKey == false)
                    {
                        var isAdd = item.IsPrimaryKey;
                        if (isAdd)
                        {
                            this.Context.SqlDbProvider.AddPrimaryKey(tableName, item.Name);
                        }
                        else
                        {
                            this.Context.SqlDbProvider.DropConstraint(tableName, string.Format("PK_{0}_{1}", tableName, item.Name));
                        }
                    }
                    else if ((pkDiff || idEntityDiff) && isMultiplePrimaryKey == false)
                    {
                        ChangeKey(entityInfo, tableName, item);
                    }
                }
                if (isMultiplePrimaryKey)
                {
                    var oldPkNames = dbColumns.Where(it => it.IsPrimaryKey).Select(it => it.Name.ToLower()).OrderBy(it => it).ToList();
                    var newPkNames = entityColumns.Where(it => it.IsPrimaryKey).Select(it => it.Name.ToLower()).OrderBy(it => it).ToList();
                    if (!Enumerable.SequenceEqual(oldPkNames, newPkNames))
                    {
                        Check.Exception(true, ErrorMessage.GetThrowMessage("Modification of multiple primary key tables is not supported. Delete tables while creating", "不支持修改多主键表，请删除表在创建"));
                    }

                }
                if (isChange && IsBackupTable)
                {
                    this.Context.SqlDbProvider.BackupTable(tableName, tableName + DateTime.Now.ToString("yyyyMMddHHmmss"), MaxBackupDataRows);
                }
            }
        }
        protected virtual void KeyAction(DbColumnInfo item, DbColumnInfo dbColumn, out bool pkDiff, out bool idEntityDiff)
        {
            pkDiff = item.IsPrimaryKey != dbColumn.IsPrimaryKey;
            idEntityDiff = item.IsIdentity != dbColumn.IsIdentity;
        }

        protected virtual void ChangeKey(DbTableInfo entityInfo, string tableName, DbColumnInfo item)
        {
            string constraintName = string.Format("PK_{0}_{1}", tableName, item.Name);
            if (this.Context.SqlDbProvider.IsAnyConstraint(constraintName))
                this.Context.SqlDbProvider.DropConstraint(tableName, constraintName);
            this.Context.SqlDbProvider.DropColumn(tableName, item.Name);
            this.Context.SqlDbProvider.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item));
            if (item.IsPrimaryKey)
                this.Context.SqlDbProvider.AddPrimaryKey(tableName, item.Name);
        }

        protected virtual void ConvertColumns(List<DbColumnInfo> dbColumns)
        {

        }
        #endregion

        #region Helper methods
        protected virtual string GetTableName(DbTableInfo entityInfo)
        {
            return entityInfo.TableName;
        }
        protected virtual DbColumnInfo EntityColumnToDbColumn(DbTableInfo entityInfo, string tableName, DbColumnInfo item)
        {
            var propertyType = Funs.GetUnderType(item.PropertyInfo);
            var result = new DbColumnInfo()
            {
                //TableId = entityInfo.Columns.IndexOf(item),
                Name = item.Name,
                IsPrimaryKey = item.IsPrimaryKey,
                IsIdentity = item.IsIdentity,
                //TableName = tableName,
                IsNullable = item.IsNullable,
                DefaultValue = item.DefaultValue,
                Description = item.Description,
                MaxLength = item.MaxLength,
                DecimalDigits = item.DecimalDigits
            };
            GetDbType(item,propertyType, result);
            return result;
        }

        protected virtual void GetDbType(DbColumnInfo item, Type propertyType, DbColumnInfo result)
        {
            if (!string.IsNullOrEmpty(item.Type))
            {
                result.Type = item.Type;
            }
            else if (propertyType.IsEnum())
            {
                result.Type = this.Context.SqlDbProvider.GetDbTypeName(item.MaxLength > 9 ? Constants.LongType.Name : Constants.IntType.Name);
            }
            else
            {
                var name = GetType(propertyType.Name);
                result.Type = this.Context.SqlDbProvider.GetDbTypeName(name);
            }
        }
        protected virtual bool IsSamgeType(DbColumnInfo ec, DbColumnInfo dc)
        {
            if (!string.IsNullOrEmpty(ec.Type))
            {
                return ec.Type != dc.Type;
            }
            var propertyType = Funs.GetUnderType(ec.PropertyInfo);
            var properyTypeName = string.Empty;
            if (propertyType.IsEnum())
            {
                properyTypeName = this.Context.SqlDbProvider.GetDbTypeName(ec.MaxLength > 9 ? Constants.LongType.Name : Constants.IntType.Name);
            }
            else
            {
                var name = GetType(propertyType.Name);
                properyTypeName = this.Context.SqlDbProvider.GetDbTypeName(name);
            }
            var dataType = dc.Type;
            if (properyTypeName == "boolean" && dataType == "bool")
            {
                return false;
            }
            return properyTypeName != dataType;
        }
        private static string GetType(string name)
        {
            if (name.IsContainsIn("UInt32", "UInt16", "UInt64"))
            {
                name = name.TrimStart('U');
            }
            if (name == "char")
            {
                name = "string";
            }
            return name;
        }

        #endregion
    }
    #endregion

    #region class SqlServerDbFirst
    internal class SqlServerDbFirst : DbFirstProvider
    {
        public SqlServerDbFirst():base()
        {
        }
        public SqlServerDbFirst(DbHelper _Context) : base(_Context)
        {
        }
        public SqlServerDbFirst(string dbName) : base(dbName)
        {
        }

        protected override string GetTableName(DbTableInfo entityInfo)
        {
            var table = entityInfo.TableName;
            var tableArray = table.Split('.');
            var noFormat = table.Split(']').Length == 1;
            if (tableArray.Length > 1 && noFormat)
            {
                return tableArray.Last();
            }
            else
            {
                return table;
            }
        }
    }
    #endregion
    #region class OracleDbFirst
    internal class OracleDbFirst : DbFirstProvider
    {
        public OracleDbFirst()
        {
            if (DefultLength == 0)
                DefultLength = 40;
        }
        public OracleDbFirst(DbHelper _Context) : base(_Context)
        {
        }
        public OracleDbFirst(string dbName) : base(dbName)
        {
        }

        protected override int DefultLength { get; set; }

        protected override void GetDbType(DbColumnInfo item, Type propertyType, DbColumnInfo result)
        {
            if (!string.IsNullOrEmpty(item.Type))
            {
                result.Type = item.Type;
            }
            else if (propertyType.IsEnum())
            {
                result.Type = this.Context.SqlDbProvider.GetDbTypeName(item.MaxLength > 9 ? Constants.LongType.Name : Constants.IntType.Name);
            }
            else
            {
                if (propertyType.Name.Equals("Guid", StringComparison.CurrentCultureIgnoreCase))
                {
                    result.Type = this.Context.SqlDbProvider.GetDbTypeName(Constants.StringType.Name);
                }
                else
                {
                    result.Type = this.Context.SqlDbProvider.GetDbTypeName(propertyType.Name);
                }
            }
        }
    }
    #endregion
    #region class MySqlDbFirst
    internal class MySqlDbFirst : DbFirstProvider
    {
        public MySqlDbFirst() : base()
        {
        }
        public MySqlDbFirst(DbHelper _Context) : base(_Context)
        {
        }
        public MySqlDbFirst(string dbName) : base(dbName)
        {
        }

        public override void NoExistLogic(DbTableInfo entityInfo)
        {
            var tableName = GetTableName(entityInfo);
            //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimaryKey).Count() > 1, "Use Code First ,The primary key must not exceed 1");
            List<DbColumnInfo> columns = new List<DbColumnInfo>();
            if (entityInfo.Columns.HasValue())
            {
                foreach (var item in entityInfo.Columns.OrderBy(it => it.IsPrimaryKey ? 0 : 1))
                {
                    if (item.IsIgnore)
                        continue;
                    if (item.PropertyInfo != null && Funs.GetUnderType(item.PropertyInfo) == Constants.GuidType && item.MaxLength == 0 && item.Type.IsNullOrEmpty())
                    {
                        item.MaxLength = Guid.NewGuid().ToString().Length;
                    }
                    DbColumnInfo dbColumnInfo = this.EntityColumnToDbColumn(entityInfo, tableName, item);
                    columns.Add(dbColumnInfo);
                }
            }
            this.Context.SqlDbProvider.CreateTable(tableName, columns, true);
        }
        protected override DbColumnInfo EntityColumnToDbColumn(DbTableInfo entityInfo, string tableName, DbColumnInfo item)
        {
            var result = base.EntityColumnToDbColumn(entityInfo, tableName, item);
            if (result.Type.Equals("varchar", StringComparison.CurrentCultureIgnoreCase) && result.MaxLength == 0)
            {
                result.MaxLength = 1;
            }
            return result;
        }

        protected override void ConvertColumns(List<DbColumnInfo> dbColumns)
        {
            foreach (var item in dbColumns)
            {
                if (item.Type == "DateTime")
                {
                    item.MaxLength = 0;
                }
            }
        }

        protected override void ChangeKey(DbTableInfo entityInfo, string tableName, DbColumnInfo item)
        {
            this.Context.SqlDbProvider.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item));
            if (!item.IsPrimaryKey)
                this.Context.SqlDbProvider.DropConstraint(tableName, null);
            if (item.IsPrimaryKey)
                this.Context.SqlDbProvider.AddPrimaryKey(tableName, item.Name);
        }
    }
    #endregion
    #region class SqliteDbFirst
    internal class SqliteDbFirst : DbFirstProvider
    {
        public SqliteDbFirst() : base()
        {
        }
        public SqliteDbFirst(DbHelper _Context) : base(_Context)
        {
        }
        public SqliteDbFirst(string dbName) : base(dbName)
        {
        }

        public override void ExistLogic(DbTableInfo entityInfo)
        {
            if (entityInfo.Columns.HasValue() && entityInfo.IsDisabledUpdateAll == false)
            {
                Check.Exception(entityInfo.Columns.Where(it => it.IsPrimaryKey).Count() > 1, "Use Code First ,The primary key must not exceed 1");

                var tableName = GetTableName(entityInfo);
                var dbColumns = this.Context.SqlDbProvider.GetColumnInfosByTableName(tableName);
                ConvertColumns(dbColumns);
                var entityColumns = entityInfo.Columns.Where(it => it.IsIgnore == false).ToList();
                var dropColumns = dbColumns
                                          .Where(dc => !entityColumns.Any(ec => dc.Name.Equals(ec.Name, StringComparison.CurrentCultureIgnoreCase)))
                                          .Where(dc => !entityColumns.Any(ec => dc.Name.Equals(ec.Name, StringComparison.CurrentCultureIgnoreCase)))
                                          .ToList();
                var addColumns = entityColumns
                                          .Where(ec => ec.Name.IsNullOrEmpty() || !dbColumns.Any(dc => dc.Name.Equals(ec.Name, StringComparison.CurrentCultureIgnoreCase)))
                                          .Where(ec => !dbColumns.Any(dc => ec.Name.Equals(dc.Name, StringComparison.CurrentCultureIgnoreCase))).ToList();
                //var alterColumns = entityColumns
                //                           .Where(ec => !dbColumns.Any(dc => dc.Name.Equals(ec.OldDbColumnName, StringComparison.CurrentCultureIgnoreCase)))
                //                           .Where(ec =>
                //                                          dbColumns.Any(dc => dc.Name.Equals(ec.Name)
                //                                               && ((!UtilMethods.GetUnderType(ec.PropertyInfo).IsEnum() && UtilMethods.GetUnderType(ec.PropertyInfo).IsIn(UtilConstants.StringType)) ||

                //                                                    IsSamgeType(ec, dc)))).ToList();
                var renameColumns = entityColumns
                    .Where(it => !string.IsNullOrEmpty(it.Name))
                    .Where(entityColumn => dbColumns.Any(dbColumn => entityColumn.Name.Equals(dbColumn.Name, StringComparison.CurrentCultureIgnoreCase)))
                    .ToList();


                var isChange = false;
                foreach (var item in addColumns)
                {
                    this.Context.SqlDbProvider.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item));
                    isChange = true;
                }
                foreach (var item in dropColumns)
                {
                    //this.Context.SqlDbProvider.DropColumn(tableName, item.Name);
                    //isChange = true;
                }
                //foreach (var item in alterColumns)
                //{
                //    //this.Context.SqlDbProvider.AddColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item));
                //    //isChange = true;
                //}
                foreach (var item in renameColumns)
                {
                    throw new NotSupportedException("rename Column");
                }

                foreach (var item in entityColumns)
                {
                    var dbColumn = dbColumns.FirstOrDefault(dc => dc.Name.Equals(item.Name, StringComparison.CurrentCultureIgnoreCase));
                    if (dbColumn == null) continue;
                    bool pkDiff, idEntityDiff;
                    KeyAction(item, dbColumn, out pkDiff, out idEntityDiff);
                    if (dbColumn != null && pkDiff && !idEntityDiff)
                    {
                        var isAdd = item.IsPrimaryKey;
                        if (isAdd)
                        {
                            this.Context.SqlDbProvider.AddPrimaryKey(tableName, item.Name);
                        }
                        else
                        {
                            this.Context.SqlDbProvider.DropConstraint(tableName, string.Format("PK_{0}_{1}", tableName, item.Name));
                        }
                    }
                    else if (pkDiff || idEntityDiff)
                    {
                        ChangeKey(entityInfo, tableName, item);
                    }
                }
                if (isChange && base.IsBackupTable)
                {
                    this.Context.SqlDbProvider.BackupTable(tableName, tableName + DateTime.Now.ToString("yyyyMMddHHmmss"), MaxBackupDataRows);
                }
            }
        }
        public override void NoExistLogic(DbTableInfo entityInfo)
        {
            var tableName = GetTableName(entityInfo);
            string backupName = tableName + DateTime.Now.ToString("yyyyMMddHHmmss");
            Check.Exception(entityInfo.Columns.Where(it => it.IsPrimaryKey).Count() > 1, "Use Code First ,The primary key must not exceed 1");
            List<DbColumnInfo> columns = new List<DbColumnInfo>();
            if (entityInfo.Columns.HasValue())
            {
                foreach (var item in entityInfo.Columns.OrderBy(it => it.IsPrimaryKey ? 0 : 1).Where(it => it.IsIgnore == false))
                {
                    DbColumnInfo dbColumnInfo = this.EntityColumnToDbColumn(entityInfo, tableName, item);
                    columns.Add(dbColumnInfo);
                }
            }
            this.Context.SqlDbProvider.CreateTable(tableName, columns, true);
        }
        protected override DbColumnInfo EntityColumnToDbColumn(DbTableInfo entityInfo, string tableName, DbColumnInfo item)
        {
            var result = base.EntityColumnToDbColumn(entityInfo, tableName, item);
            if (result.Type.Equals("varchar", StringComparison.CurrentCultureIgnoreCase) && result.MaxLength == 0)
            {
                result.MaxLength = 1;
            }
            return result;
        }

        protected override void ConvertColumns(List<DbColumnInfo> dbColumns)
        {
            foreach (var item in dbColumns)
            {
                if (item.Type == "DateTime")
                {
                    item.MaxLength = 0;
                }
            }
        }

        protected override void ChangeKey(DbTableInfo entityInfo, string tableName, DbColumnInfo item)
        {
            this.Context.SqlDbProvider.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item));
            if (!item.IsPrimaryKey)
                this.Context.SqlDbProvider.DropConstraint(tableName, null);
            if (item.IsPrimaryKey)
                this.Context.SqlDbProvider.AddPrimaryKey(tableName, item.Name);
        }
    }
    #endregion
    #region class PostgreSQLDbFirst
    internal class PostgreSQLDbFirst : DbFirstProvider
    {
        public PostgreSQLDbFirst() : base()
        {
        }
        public PostgreSQLDbFirst(DbHelper _Context) : base(_Context)
        {
        }
        public PostgreSQLDbFirst(string dbName) : base(dbName)
        {
        }

        public override void NoExistLogic(DbTableInfo entityInfo)
        {
            var tableName = GetTableName(entityInfo);
            //Check.Exception(entityInfo.Columns.Where(it => it.IsPrimaryKey).Count() > 1, "Use Code First ,The primary key must not exceed 1");
            List<DbColumnInfo> columns = new List<DbColumnInfo>();
            if (entityInfo.Columns.HasValue())
            {
                foreach (var item in entityInfo.Columns.Where(it => it.IsIgnore == false))
                {
                    DbColumnInfo dbColumnInfo = this.EntityColumnToDbColumn(entityInfo, tableName, item);
                    columns.Add(dbColumnInfo);
                }
            }
            this.Context.SqlDbProvider.CreateTable(tableName, columns, true);
        }
        protected override DbColumnInfo EntityColumnToDbColumn(DbTableInfo entityInfo, string tableName, DbColumnInfo item)
        {
            var result = base.EntityColumnToDbColumn(entityInfo, tableName, item);
            if (result.Type.Equals("varchar", StringComparison.CurrentCultureIgnoreCase) && result.MaxLength == 0)
            {
                result.MaxLength = 1;
            }
            return result;
        }

        protected override void ConvertColumns(List<DbColumnInfo> dbColumns)
        {
            foreach (var item in dbColumns)
            {
                if (item.Type == "DateTime")
                {
                    item.MaxLength = 0;
                }
            }
        }

        protected override void ChangeKey(DbTableInfo entityInfo, string tableName, DbColumnInfo item)
        {
            this.Context.SqlDbProvider.UpdateColumn(tableName, EntityColumnToDbColumn(entityInfo, tableName, item));
            if (!item.IsPrimaryKey)
                this.Context.SqlDbProvider.DropConstraint(tableName, null);
            if (item.IsPrimaryKey)
                this.Context.SqlDbProvider.AddPrimaryKey(tableName, item.Name);
        }

    }
    #endregion
}
